﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ProtocoloCarSharing
{
    public class MensajeProtocolo : MarshalByRefObject
    {
        private Protocolo.Header header;
        private Protocolo.Comando cmd;
        private int largo;
        private string datos;

        public string Datos
        {
            get { return datos; }
            set { datos = value; }
        }

        public Protocolo.Header Header
        {
            get { return header; }
            set { header = value; }
        }

        public int Largo
        {
            get { return largo; }
            set { largo = value; }
        }

        public Protocolo.Comando Cmd
        {
            get { return cmd; }
            set { cmd = value; }
        }

        public MensajeProtocolo()
        {
        }

        public MensajeProtocolo(Protocolo.Header header, Protocolo.Comando comando, int largoDatos, string datosAMandar)
        {
            this.header = header;
            this.cmd = comando;
            this.largo = largoDatos;           
            this.datos = datosAMandar + Protocolo.END_OF_MSJ;
        }

        public MensajeProtocolo(byte[] paqueteMsjProtocolo)
        {
            byte[] encabezado = paqueteMsjProtocolo.Take(10).ToArray();
            byte[] datosBytes = paqueteMsjProtocolo.Skip(10).ToArray();

            string strPaquete = Encoding.ASCII.GetString(encabezado, 0, 10);
            string msjDatos = "";
            try
            {
                Protocolo.Header msjHead = Protocolo.Header.REQ;
                if (strPaquete.Remove(3) == Protocolo.RES)
                    msjHead = Protocolo.Header.RES;

                strPaquete = strPaquete.Remove(0, 3);
                int msjCmd = Int32.Parse(strPaquete.Remove(2));
                strPaquete = strPaquete.Remove(0, 2);
                int msjLargo = Int32.Parse(strPaquete);

                msjDatos = Encoding.ASCII.GetString(datosBytes);

                this.Header = msjHead;
                this.Cmd = (Protocolo.Comando)msjCmd;
                this.Largo = msjLargo;
                this.Datos = msjDatos;
                
            }
            catch (Exception)
            {
                this.Header = Protocolo.Header.RES;
                this.Cmd = Protocolo.Comando.VACIO;
                this.Largo = 0;
                this.Datos = msjDatos;
            }
        }

        public byte[] ConvertirAByte()
        {
            int largoCLargo = largo.ToString().Length;
            int largoCom = ((int)cmd).ToString().Length;

            string strLargo = "";
            for (int i = 0; i < 5 - largoCLargo; i++)
            {
                strLargo += "0";
            }
            strLargo += largo.ToString();

            string strCmd;
            if (largoCom == 1)
                strCmd = "0" + ((int)cmd).ToString();
            else
                strCmd = ((int)cmd).ToString();

            string mensaje = header.ToString() + strCmd + strLargo + datos;

            byte[] mensajeBytes = Encoding.ASCII.GetBytes(mensaje);
            
            return mensajeBytes;
        }

        public List<string> InfoDatos()
        {
            string[] sepArray = new string[]{Protocolo.SEPARADOR,Protocolo.END_OF_MSJ};
            string[] strArr = datos.Trim().Split(sepArray,StringSplitOptions.RemoveEmptyEntries);
            List<string> res = new List<string>();
            foreach (string s in strArr)
            {
                if (!s.Equals("")) res.Add(s);
            }
            return res;
        }
    }

    public class Protocolo : MarshalByRefObject
    {
        public enum Comando
        {
            VACIO = 99,
            IDENTIFICAR_USUARIO = 10,
            ESTADO_VIAJE = 11,
            CONSUMO = 12,
            FIN_VIAJE = 13,
            SERVIDOR_FUERA_DE_SERVICIO = 14
        }

        public enum Header { RES, REQ }

        public const string REQ = "REQ";
        public const string RES = "RES";

        public const string OK = "OK";
        public const string ERROR = "Error";
        public const string SIN_SALDO_DISP = "SinSaldo";

        public const string SEPARADOR = "<SEP>";
        public const string END_OF_MSJ = "<EOF>";

        public const string EN_SERVICIO = "En Servicio";
        public const string FUERA_DE_SERVICIO = "Fuera de Servicio";

    }
}
